# Create your views here.
from django.shortcuts import render_to_response
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.contrib.auth import logout
from django.template import RequestContext
from django.db import transaction
from market.controllerCreateBetroomView import createBetroom2
from market.sendEmailToPlayers import sendEmailToPlayersOfTheBetroom
from market.authentification import authentificatePlayer, authentificateUser
from market.models import UserProfile
from market.models import BetRoom, Strategy, AssetPercentageInStrategy, Fund
from market.models import Asset, Player, History
from market.playerData import PlayerData
from market.marketData import MarketData
from market.strategyAndFundHelper import getFundMtM, getPortfolioMtM, isStrategyValid, getBankAccount
from market.marketAction import SubmitNewRepartition0
from django.utils import simplejson
from market.chat import xmpp
from market.chat.createChatRoom import createChatRoom

from market.stupidUserException import StupidUserException
from market.exceptionHandler import handleRequestPlayerPOSTWithExceptionWhenNotSuspended
from market.exceptionHandler import handleRequestBetroomPOSTWithException, handleRequestBetroomAdminPOSTWithException


import os, os.path
from market.baseCreator import constructRoomFromFiles
from market.baseSaver import saveRoomToFiles


################################################################################################################
# allow to create a new betroom
def createBetroom(request):
        
        alternative_response_list = [] #the answer to return if the player could not be authentificated with a dummy initialisation
        if not( authentificateUser( request, alternative_response_list ) ):
                return alternative_response_list[0]

        if len( BetRoom.objects.filter( personInCharge = request.user, status__lte = 0 ) ):
                raise Exception('There should be just one betroom per user being launched at once.')

        betroomName = request.POST['newBetroomName']
        if betroomName == "":
                return HttpResponseRedirect("/createBetroom/step1/")

        betrooms = BetRoom.objects.filter( name = betroomName )
        if len(betrooms) != 0:
                return render_to_response('CreateBetroom/createBetroom1.html',
                                        {'userName':request.user.username, 'message':'This name is already used, please select an other name.' },
                                        context_instance=RequestContext(request) )

        

        if ' ' in betroomName:
                return render_to_response('CreateBetroom/createBetroom1.html',
                                        {'userName':request.user.username, 'message':'Please enter a name with no space' },
                                        context_instance=RequestContext(request) )

        newBetroomPswd = request.POST['newBetroomPswd']
        if newBetroomPswd == "":
                return render_to_response('CreateBetroom/createBetroom1.html',
                                        {'userName':request.user.username, 'message':'Please enter a name with no space AND a password' },
                                        context_instance=RequestContext(request) )

        
        betroomTypeStr = request.POST['betroomType']
        if betroomTypeStr == "by_contact":
                betroomType = 1# by contract
        else:
                betroomType = 0# by repartition
        

        betroom = BetRoom(
                roomType = betroomType,
                personInCharge = request.user, # account holder in charge of the administration of the bet room 
                name = betroomName,
                password = newBetroomPswd,
                status =-1 # being launched
                )
        if betroomType == 1:
                betroom.status = 0 # there is no asset to validate in a "by contract" bet room
        betroom.save()

        # create the bank account and the bank accout strat
        bankAccountUnit = Asset(
                name = 'BAU'+ betroom.name,
                betroom = betroom, # betroom in which we can trade this asset
                isAvailableForStandardStrategy = False,
                valueMultiplier = 1,
                fixValue = 1,
                isStandard = False, # false for the banck account and the bond.
                description = 'Bank account unit of ' + betroom.name #description of what this asset is. What is the event associated to it, ...
                )
        bankAccountUnit.save()

        bankAccount = Strategy(
                betroom = betroom, # betroom in which we can trade this asset
                name = 'BankAccount'+ betroom.name
                )
        bankAccount.save()

        pin = AssetPercentageInStrategy(
                asset = bankAccountUnit,
                strategy = bankAccount,
                assetPercentageInStrategy = 1# the percentage is user-defined and is an float
                )
        pin.save()

        if betroomType == 1:# the administrator is automaticly suggested as a player
                administatorPlayer = Player( userBeingThisPlayer = request.user, mainStrategy = bankAccount )
                administatorPlayer.save()

        profile = request.user.get_profile()
        profile.nameOfTheLastVistedBetRoom = betroomName 
        profile.save()
       
        
        request.user.nameOfTheLastVistedBetRoom = betroom.name
        request.user.save()
        return createBetroom2(request)


################################################################################################################
# allow to create a new asset in the new betroom before the assets have been validated
def createAsset0(request, betroom):

        if betroom.status != -1:
                raise Exception("Asset can only be added when the bet room is being launched before the assets have been validated.")

        assetName = request.POST['asset_name']
        if assetName == "":
                return HttpResponseRedirect("/createBetroom/step3/")

        if ' ' in assetName:
                return render_to_response('CreateBetroom/createBetroom3.html',
                                        {'userName':request.user.username,
                                         'betroom': betroom,
                                         'message':'Please enter a name with no space' },
                                        context_instance=RequestContext(request) )

        if len( Asset.objects.filter( name = assetName ) ) != 0:
                return render_to_response('CreateBetroom/createBetroom3.html',
                                        {'userName':request.user.username,
                                         'betroom': betroom,
                                         'message':'Sorry, this asset name is already taken, chose another name.' },
                                        context_instance=RequestContext(request) )
        
        
        # create the bank account and the bank accout strat
        newAsset = Asset(
                name = assetName,
                betroom = betroom, # betroom in which we can trade this asset
                isAvailableForStandardStrategy = True,
                valueMultiplier = 1,
                fixValue = -1,
                isStandard = ('check_std' in request.POST), # false for the banck account and the bond.
                description = request.POST['asset_desc_text']
                )
        newAsset.save()
        return HttpResponseRedirect("/createBetroom/step3/")

################################################################################################################
# allow to create a new asset in the new betroom before the assets have been validated
def createAsset(request):
        return handleRequestBetroomAdminPOSTWithException( globals()["createAsset0"], request )
        

################################################################################################################
# allow for editing the asset description
def changeNewAsset0(request, betroom):
        asset = Asset.objects.get( name = request.POST['asset_name'] )
        asset.isStandard = ('check_std' in request.POST)
        asset.description = request.POST['asset_desc_text']
        asset.save()
        return HttpResponseRedirect("/createBetroom/step3/")

################################################################################################################
# allow for editing the asset description
def changeNewAsset(request):
        return handleRequestBetroomAdminPOSTWithException( globals()["changeNewAsset0"], request )

################################################################################################################
# allow for deleting a new asset in the new betroom before that the assets have been validated
def deleteNewAsset0(request, betroom):

        if betroom.status != -1:
                raise Exception("Asset can only be deleted when the bet room is being launched before the assets have been validated.")
        asset = Asset.objects.get( name = request.POST['asset_name'] )
        asset.delete()
        return HttpResponseRedirect("/createBetroom/step3/")

################################################################################################################
# allow for deleting a new asset in the new betroom before that the assets have been validated
def deleteNewAsset(request):
        return handleRequestBetroomAdminPOSTWithException( globals()["deleteNewAsset0"], request )
                

################################################################################################################
# allow to validate the assets. Once the assets have been validated, The names and number of the asset in the betroom 
# cannot be changed. The status is updated to 0 (-1 before validation, 1 when running)
def validateAssets0(request, betroom):
        assets = Asset.objects.filter( betroom =  betroom, isAvailableForStandardStrategy = True )
        if len( assets ) == 0:
                raise StupidUserException('Maybe you have not noticed yet, but you cannot validate asset since there is no asset to validate!')
        betroom.status = 0
        betroom.save()
        return HttpResponseRedirect("/createBetroom/step3/")

################################################################################################################
# allow to validate the assets. Once the assets have been validated, The names and number of the asset in the betroom 
# cannot be changed. The status is updated to 0 (-1 before validation, 1 when running)
def validateAssets(request):
        return handleRequestBetroomAdminPOSTWithException( globals()["validateAssets0"], request )
     

################################################################################################################
# allow to create a new player and its strat in the new betroom
def createStratAndPlayer( userToBecomeAPlayer, betroom ):

        # if we play with percentage, each player has his main strat
        if betroom.roomType == 0:
                newStrat = Strategy(
                        betroom = betroom, # betroom in which we can trade this asset
                        name = betroom.name+userToBecomeAPlayer.username+'Strat'
                        )
                newStrat.save()
        else:# all the player have only access to the bank account
                newStrat = getBankAccount(betroom)

        newPlayerList = Player.objects.filter( mainStrategy__betroom = betroom, userBeingThisPlayer = userToBecomeAPlayer )
        if len(newPlayerList) > 0:
                return
        newPlayer = Player(
                userBeingThisPlayer = userToBecomeAPlayer, # account holder in charge of this player
                mainStrategy = newStrat # main strategy of the player
                )
        newPlayer.save()
        
        # if we play with percentage, initialise the percentage equally on the assets
        if betroom.roomType == 0:
                assets = Asset.objects.filter( betroom =  betroom, isAvailableForStandardStrategy = True )
                if len( assets ) == 0:
                         raise Exception('trying to create strategy with no asset')
                else:
                        for a in assets:
                                ais = AssetPercentageInStrategy(
                                        asset = a,
                                        strategy = newStrat,
                                        assetPercentageInStrategy = 1 / float(len(assets))
                                        )
                                ais.save()
                                
        userToBecomeAPlayer.get_profile().nameOfTheLastVistedBetRoom = betroom.name
        userToBecomeAPlayer.save()
        return
        

################################################################################################################
# create a player for the admin or delete it according to the request
def adminOrPlayer0(request, betroom):
        if betroom.status != 0:
                raise Exception("Player can only be added when the bet room is being launched after the assets have been validated.")

        players = Player.objects.filter( mainStrategy__betroom = betroom, userBeingThisPlayer = request.user )
        if( len(players) > 1 ):
                raise Exception('adminOrPlayer0: There should be only one player with the admin name')
        # if only admin, we delete the player of the administrator if he exists
        if  request.POST['playerOrAdmin'] != 'player' :
                if( len(players) == 1 ):
                        # this should be enough to delete the player and the AssetPercentageInStrategy and the Fund attached to it
                        players[0].mainStrategy.delete()
                #if 0, do nothing
        else:#check that we have a valid player or create it
                createStrat =  False
                if( len(players) == 0 ):
                        createStrat = True
                else:#
                        tmp = isStrategyValid( players[0].mainStrategy )
                        if not( tmp[0] ):
                                players[0].mainStrategy.delete()
                                createStrat = True
                if( createStrat ):
                            createStratAndPlayer( request.user, betroom )
        
        return HttpResponseRedirect("/createBetroom/step4/")

################################################################################################################
# create a player for the admin or delete it according to the request
def adminOrPlayer(request):
        return handleRequestBetroomAdminPOSTWithException( globals()["adminOrPlayer0"], request )



################################################################################################################
# allow to set a new view in the market before it is launched
def setView0(request, betroom):
        if betroom.status != 0:
                raise Exception("Player can only be added when the bet room is being launched after the assets have been validated.")

        players = Player.objects.filter( mainStrategy__betroom = betroom, userBeingThisPlayer = request.user )
        if( len(players) > 1 ):
                raise Exception('setView0: There should be only one player with the this name')
        if( len(players) == 0 ):
                return 0
        player = PlayerData( players[0].userBeingThisPlayer, players[0].mainStrategy.betroom )
        return SubmitNewRepartition0( request, player )
        

################################################################################################################
# allow to set the view of the player who is also the admin
def setViewAdmin(request):
        return handleRequestBetroomAdminPOSTWithException( globals()["setView0"], request )


################################################################################################################
# allow to set the player view in  the betroom
def setViewPlayer(request):
        return handleRequestBetroomPOSTWithException( globals()["setView0"], request )
        

################################################################################################################
# allow to create a new player in the new betroom
def createPlayer(request):
        alternative_response = []
        if not(authentificateUser(request, alternative_response )):
                return alternative_response[0]

        try:
                betroom = BetRoom.objects.get( name = request.POST['betroom'] )
        except:
                return HttpResponseRedirect("/betrooms/")

        if betroom.status != 0:
                raise Exception("Player can only be added when the bet room is being launched after the assets have been validated.")

        try:
                newBetroomPswd =  request.POST['newBetroomPswd']
        except:
                return HttpResponseRedirect("/betrooms/")
        
        if newBetroomPswd == betroom.password:
                createStratAndPlayer( request.user, betroom )
                return HttpResponseRedirect("/enterBetroom/step2/")
        else:
                return HttpResponseRedirect("/enterBetroom/step1/") 


################################################################################################################
# delete the betrooom at the admin command instead of launching it
def deleteBetroom0(request, betroom):
        betroom.delete()
        return HttpResponseRedirect("/betrooms/")
        

################################################################################################################
# delete the betrooom at the admin command instead of launching it
def deleteBetroom(request):
        return handleRequestBetroomAdminPOSTWithException( globals()["deleteBetroom0"], request )


################################################################################################################
# launch the betrooom at the admin command
def launchBetroom0(request, betroom):
        constantMtM = 10000
        bankAccount = getBankAccount(betroom)

        if betroom.roomType == 0:#all player are initially fully invested in their own strategy
                playerStrats = Strategy.objects.filter( betroom = betroom )
                for strat in playerStrats:
                        if strat != bankAccount:
                                player = Player.objects.get( mainStrategy = strat )
                                if request.POST.get( player.userBeingThisPlayer.username, 'off') == 'on':
                                        fund = Fund(
                                                player = player,#the owner of the fund
                                                strategy = strat,
                                                fundTargetPercentageInPortfolio = 1 )
                                        fund.save()
                                else:
                                        player.delete()
                        
                
                #now the player are all in and only the one which were checked
                mkt = MarketData(betroom)
                playerStrats = Player.objects.filter( mainStrategy__betroom = betroom )
                for player in playerStrats:
                        pd = PlayerData( player.userBeingThisPlayer, betroom  )
                        pd.setNumberOfAssetPerStrategy( constantMtM, [(Fund.objects.get( strategy = player.mainStrategy ), 1)], mkt )

                
        else:#all player are initially (and remain) fully invested in the bank account
                players = Player.objects.filter( mainStrategy__betroom = betroom )
                for p in players:
                        if request.POST.get( p.userBeingThisPlayer.username, 'off') == 'on':
                                fund = Fund(
                                        player = p,#the owner of the fund
                                        strategy = bankAccount,
                                        numberOfAssetsInFund = constantMtM,
                                        fundTargetPercentageInPortfolio = 1 )
                                fund.save()
                        else:
                                player.delete()
                
        betroom.status = 1
        betroom.save()

        histories = History.objects.filter( betroom = betroom )
        for h in histories:
                h.delete()
        
         
        # send an email to all the participants
        sendEmailToPlayersOfTheBetroom(
                betroom,
		'Bet room ' + betroom.name + ' is now running!',
                'Connect to Celibax at http://polux.alwaysdata.net/ to follow the market evolution and change you bet in real time!'
            )
        
        return HttpResponseRedirect("/betrooms/")
        

################################################################################################################
# launch the betrooom at the admin command
def launchBetroom(request):
        return handleRequestBetroomAdminPOSTWithException( globals()["launchBetroom0"], request )


